﻿using System;
using NHibernate.Cfg;
using NHibernate;
using System.Data;
using System.Data.SQLite;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Mapping.ByCode;
using MVCQuick.Framework.Repository.NHibernate;
using System.Diagnostics;
using System.Reflection;

namespace MVCQuick.Framework.Tests
{
    public class SQLiteDbManager : IDisposable
    {
        private const string CONNECTION_STRING = "Data Source=:memory:;Version=3;New=True;";       

        private Configuration configuration;
        private ISessionFactory sessionFactory;
        private IDbConnection dbConnection;

        public ISessionFactory SessionFactory
        {
            get
            {
                if (sessionFactory == null)
                {
                    sessionFactory = configuration.BuildSessionFactory();
                }
                return sessionFactory;
            }
        }

        public IDbConnection DbConnection
        {
            get
            {
                if (dbConnection == null)
                {
                    dbConnection = new SQLiteConnection(CONNECTION_STRING);
                    dbConnection.Open();
                }
                return dbConnection;
            }
        }

        public SQLiteDbManager()
        {
            Configuration();
        }

        private void Configuration()
        {
            configuration = new Configuration();
            configuration.SetProperty("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
            configuration.SetProperty("connection.driver_class", "NHibernate.Driver.SQLite20Driver");
            configuration.SetProperty("dialect", "NHibernate.Dialect.SQLiteDialect");
            configuration.SetProperty("connection.connection_string", CONNECTION_STRING);            
            configuration.SetProperty("show_sql", "true");
        }

        public void AddMapping(string appName, params Assembly[] assemblies)
        {
            ModelMapper mapper = new ModelMapper(new EntityModelInspector());
            mapper.AddEntityMappings(appName + "_", assemblies);
            var hbmMappings = mapper.CompileMappingForAllExplicitlyAddedEntities();

            Debug.WriteLine(hbmMappings.AsString());
           
            configuration.AddDeserializedMapping(hbmMappings, appName + "Mappings");
        }

        public void UpdateSchema()
        {
            SchemaExport se = new SchemaExport(configuration);

            se.Execute(false, true, false, DbConnection, Console.Out);
        }

        public ISession OpenSession()
        {
            return SessionFactory.OpenSession(DbConnection);
        }

        private bool disposedValue = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    if (dbConnection != null)
                    {
                        dbConnection.Close();
                    }
                    dbConnection = null;

                }
            }

            disposedValue = true;
        }


        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

    }
}
